#include "dispatch.h"

#include "global.h"

#include <QTimer>
#include <QFile>
#include <QTextStream>
#include <QFileSystemWatcher>
#include <QCoreApplication>
#include <QRegExp>

Dispatch::Dispatch(QObject *parent) :
    watcher(new QFileSystemWatcher(this)),
    QObject(parent)
{
    QString appDir = QCoreApplication::applicationDirPath();
    QString passSuffix = appDir+"/"+DCM_PASS_SUFFIX_LIST_FILE;
    QString denySuffix = appDir+"/"+DCM_DENY_SUFFIX_LIST_FILE;
    watcher->addPath(passSuffix);
    watcher->addPath(denySuffix);
    connect(watcher, SIGNAL(fileChanged(QString)), this, SLOT(loadSuffixFile(QString)));
    loadSuffixFile(passSuffix);
    loadSuffixFile(denySuffix);
}

void Dispatch::loadSuffixFile(const QString &file)
{
    QFile dev(file);
    QStringList suffixs;

    if (dev.open(QIODevice::ReadOnly|QIODevice::Text)) {
        QTextStream in(&dev);
        while (!in.atEnd()) {
            QString s = in.readLine();
            if (!s.isEmpty()) suffixs += s;
        }

        if (file.endsWith(DCM_PASS_SUFFIX_LIST_FILE))
            m_passSuffix = suffixs;
        else m_denySuffix = suffixs;
    }
}

void Dispatch::dispatchFile(const QString &file)
{
    QString suffix = suffixOf(file);
    if (m_passSuffix.contains(suffix, Qt::CaseInsensitive) || isUidFileName(file)) prependParse(file);
    else if (!m_denySuffix.contains(suffix, Qt::CaseInsensitive)) prependVerify(file);
}

void Dispatch::startDispatch()
{
    if (!m_files.isEmpty()) {
        QString f = m_files.takeFirst();
        QString suffix = suffixOf(f);
        if (m_passSuffix.contains(suffix, Qt::CaseInsensitive) || isUidFileName(f)) appendParse(f);
        else if (!m_denySuffix.contains(suffix, Qt::CaseInsensitive)) appendVerify(f);
        QTimer::singleShot(0, this, SLOT(startDispatch()));
    }
}

void Dispatch::fileAdded(const QString &file)
{
    m_files += file;
    QTimer::singleShot(0, this, SLOT(startDispatch()));
}

void Dispatch::filesAdded(const QStringList &files)
{
    m_files += files;
    QTimer::singleShot(0, this, SLOT(startDispatch()));
}

void Dispatch::onFileRemoved(const QString &file)
{
    if (m_passSuffix.contains(suffixOf(file), Qt::CaseInsensitive) || isUidFileName(file))
        emit fileRemoved(file);
}

void Dispatch::onFileRenamed(const QString &oldName, const QString &newName)
{
    if (m_passSuffix.contains(suffixOf(oldName), Qt::CaseInsensitive) || isUidFileName(oldName))
        emit fileRenamed(oldName, newName);
}

bool Dispatch::isUidFileName(const QString &file)
{
    QRegExp exp("[0-9.]+");
    return exp.exactMatch(file.mid(file.lastIndexOf("/")+1));
}

QString Dispatch::suffixOf(const QString &file)
{
    QString f = file;
    QString suffix;
    f = f.mid(f.lastIndexOf("/")+1);
    int dotIdx = f.lastIndexOf(".");
    if (dotIdx >= 0)
        suffix = f.mid(dotIdx+1);
    return suffix;
}

void Dispatch::prependParse(const QString &file)
{
    gParseMutex.lock();
    gParseList.prepend(file);
    gParseCond.wakeAll();
    gParseMutex.unlock();
}

void Dispatch::appendParse(const QString &file)
{
    gParseMutex.lock();
    gParseList.append(file);
    gParseCond.wakeAll();
    gParseMutex.unlock();
}

void Dispatch::prependVerify(const QString &file)
{
    gVerifyMutex.lock();
    gVerifyList.prepend(file);
    gVerifyCond.wakeAll();
    gVerifyMutex.unlock();
}

void Dispatch::appendVerify(const QString &file)
{
    gVerifyMutex.lock();
    gVerifyList.append(file);
    gVerifyCond.wakeAll();
    gVerifyMutex.unlock();
}
